#pragma once

#include "engine/hash_map.h"
#include "engine/math.h"
#include "engine/resource.h"

namespace Lumix
{

class Model;
struct Pose;
struct Quat;
struct Vec3;


struct BoneMask
{
	BoneMask(IAllocator& allocator) : bones(allocator) {}
	StaticString<32> name;
	HashMap<u32, u8> bones;
};


class Animation final : public Resource
{
	public:
		static const u32 HEADER_MAGIC = 0x5f4c4146; // '_LAF'
		static const ResourceType TYPE;

	public:
		struct Header
		{
			u32 magic;
			u32 version;
			Time length;
		};

	public:
		Animation(const Path& path, ResourceManager& resource_manager, IAllocator& allocator);

		ResourceType getType() const override { return TYPE; }

		int getRootMotionBoneIdx() const { return m_root_motion_bone_idx; }
		LocalRigidTransform getBoneTransform(Time time, int bone_idx) const;
		void getRelativePose(Time time, Pose& pose, const Model& model, const BoneMask* mask) const;
		void getRelativePose(Time time, Pose& pose, const Model& model, float weight, const BoneMask* mask) const;
		Time getLength() const { return m_length; }
		int getBoneCount() const { return m_bones.size(); }
		int getBoneIndex(u32 name) const;

	private:
		void unload() override;
		bool load(u64 size, const u8* mem) override;

	private:
		IAllocator& m_allocator;
		Time m_length;
		struct Bone
		{
			u32 name;
			int pos_count;
			const u16* pos_times;
			const Vec3* pos;
			int rot_count;
			const u16* rot_times;
			const Quat* rot;
		};
		Array<Bone> m_bones;
		Array<u8> m_mem;
		int m_root_motion_bone_idx;
};


} // namespace Lumix
